﻿Imports System.IO
Public MustInherit Class TypeProvider
#Region "Field"
    Private _Writer As TextWriter
    Private _Reader As TextReader
    Private _Info As CompilerInfo
#End Region
#Region "Properties"
    Public ReadOnly Property NewLine As String
        Get
            Return Environment.NewLine
        End Get
    End Property
    Public ReadOnly Property Reader As TextReader
        Get
            Return _Reader
        End Get
    End Property
    Public ReadOnly Property Writer As TextWriter
        Get
            Return _Writer
        End Get
    End Property
    Public ReadOnly Property Info As CompilerInfo
        Get
            Return _Info
        End Get
    End Property
    Public MustOverride ReadOnly Property Types As Type()
#End Region
#Region "Methods"
    'Friend & Basic
    Friend Sub Initialize(I As CompilerInfo, R As TextReader, W As TextWriter)
        _Info = I
        _Reader = R
        _Writer = W
    End Sub
    Friend Shadows Sub Finalize()
        _Info = Nothing
        _Reader = Nothing
        _Writer = Nothing
    End Sub

    'Public & Writers
    Public Sub Write(Text As String)
        Writer.Write(Text)
    End Sub
    Public Sub StartBlock()
        Write(Info.StartBlock)
        If Info.Format Then
            Write(NewLine)
            AddTab()
            PutTabs()
        End If
    End Sub
    Public Sub EndBlock()
        Write(Info.EndBlock)
        If Info.Format Then
            Write(NewLine)
            RemoveTab()
            PutTabs()
        End If
    End Sub
    Public Sub WriteLine()
        Write(NewLine)
        If Info.Format Then PutTabs()
    End Sub
    Public Sub WriteVariableName(Name As String)
        Write(Info.VariableName + Name)
        If Info.Format Then Write(" ")
        Write(Info.VariableValue)
        If Info.Format Then Write(" ")
    End Sub
    Public Sub WriteType(T As Type)
        Dim n As String = ""
        If Info.PsudoTypeNameProvider IsNot Nothing Then
            n = Info.PsudoTypeNameProvider(T)
        Else
            n = T.FullName
        End If
        Write(n)
    End Sub
    'Private & Writer
    Private Sub AddTab()
        Info.Tabs += vbTab
    End Sub
    Private Sub RemoveTab()
        If Info.Tabs.Length <> 0 Then
            Info.Tabs = Left(Info.Tabs, Info.Tabs.Length - 1)
        End If
    End Sub
    Private Sub PutTabs()
        Write(Info.Tabs)
    End Sub

    'Public & Readers
    Public Function ReadBlock() As String
        Dim sx As String = ""
        While Reader.Peek <> -1
            Dim Ch = Chr(Reader.Read)
            If Ch = Info.EndBlock Then
                Exit While
            Else
                sx += Ch
            End If
        End While
        Return sx
    End Function
    Public Function ReadVariableName() As String
        While Reader.Peek <> -1
            Dim Ch = Chr(Reader.Read)
            If TypeProvider.IsValidChar(Ch) Then
                If Ch = Info.EndBlock Then
                    Return Nothing
                End If
                If Ch <> Info.VariableName Then
                    Throw New Exception("Invalid Input Stream")
                End If
                Dim FieldName = ""
                While Reader.Peek <> -1
                    Ch = Chr(Reader.Read)
                    If Ch = Info.VariableValue Then
                        Exit While
                    End If
                    If TypeProvider.IsValidChar(Ch) Then
                        FieldName += Ch
                    End If
                End While
                Return FieldName
            End If
        End While
        Return ""
    End Function
    Public Function ReadNull() As Boolean
        If Reader.Peek <> -1 And Chr(Reader.Peek) = Info.Null Then
            Return True
        Else
            Return False
        End If
    End Function

    'Others
    Public Shared Function IsValidChar(Ch As Char) As Boolean
        If Ch <> " " And Not vbTab.Contains(Ch) And Not Environment.NewLine.Contains(Ch) Then
            Return True
        Else
            Return False
        End If
    End Function

    'Main
    Public MustOverride Sub WriteObject(Obj As Object)
    Public MustOverride Function ReadObject(T As Type) As Object
#End Region
End Class